





# Pandas 数据结构：Series 与 DataFrame


# Series
# 创建：pd.Series(data, index, dtype)
# 属性：.index, .values, .dtype, .name
# 操作：索引、切片、矢量化运算

# DataFrame
# 创建：pd.DataFrame(data, columns, index)
# 属性：.columns, .index, .shape, .dtypes, .info()
# 行列操作：增删改查（df['col'], df.loc[], df.iloc[]）


# Series：一维标签化数组
import pandas as pd
import numpy as np

# 从列表创建（自动生成整数索引）
s1 = pd.Series([10, 20, 30, 40])
# 指定索引和数据类型
s2 = pd.Series(data=[5, 6, 7], index=['a', 'b', 'c'], dtype=np.float32)
# 从字典创建（键作为索引）
s3 = pd.Series({'北京': 2154, '上海': 2428, '广州': 1867})

print(s3.index)    # Index(['北京', '上海', '广州'], dtype='object')
print(s3.values)   # [2154 2428 1867]
print(s3.dtype)    # int64
s3.name = "人口(万)"  # 设置Series名称

# 1. 高级索引
print(s3[['上海', '广州']])  # 标签索引
print(s3[s3 > 2000])       # 布尔索引

# 2. 矢量化运算（自动对齐索引）
s4 = pd.Series({'北京': 100, '上海': 200, '深圳': 300})
print(s3 + s4)  # 深圳→NaN（索引对齐）

# 3. 函数应用
log_pop = s3.apply(np.log)  # 应用对数函数















# 从字典创建（键→列名）
data = {
    '城市': ['北京', '上海', '广州'],
    'GDP(亿)': [40269, 43214, 28232],
    '人口(万)': [2154, 2428, 1867]
}
df = pd.DataFrame(data, index=['A', 'B', 'C'])

# 从嵌套列表创建（指定列名）
df2 = pd.DataFrame(
    [[40269, 2154], [43214, 2428], [28232, 1867]],
    columns=['GDP(亿)', '人口(万)'],
    index=['北京', '上海', '广州']
)



print(df.columns)  # Index(['城市', 'GDP(亿)', '人口(万)'], dtype='object')
print(df.index)    # Index(['A', 'B', 'C'], dtype='object')
print(df.shape)    # (3, 3)
print(df.dtypes)   # 各列数据类型
df.info()          # 内存布局和数据类型摘要





# 1. 列操作
df['人均GDP'] = df['GDP(亿)'] / df['人口(万)'] * 10000  # 新增列
df.drop(columns=['人口(万)'], inplace=True)          # 删除列

# 2. 行操作（loc基于标签，iloc基于位置）
print(df.loc['A'])                 # 获取索引'A'的行
df.loc['D'] = ['深圳', 30665, 8.2]  # 新增行
df.drop(index='C', inplace=True)    # 删除行

# 3. 高级索引
print(df.loc[['A', 'D'], ['城市', '人均GDP']])  # 行列标签组合
print(df.iloc[0:2, 1:3])                      # 位置切片

# 4. 条件筛选
high_gdp = df[df['GDP(亿)'] > 40000]  # GDP超4万亿的城市










# 关键结论：

# Series 是带索引的一维数组，DataFrame 是多个Series的列集合
# 始终优先使用 loc/iloc 和矢量化操作，避免循环
# 索引对齐机制是Pandas数据处理的核心优势
# 类型优化（downcast）可显著降低内存占用





















# 数据清洗
#     缺失值处理
#         检测：df.isna(), df.isnull()
#         删除：df.dropna()
#         填充：df.fillna(), 插值法

#     重复值处理
#         检测：df.duplicated()
#         删除：df.drop_duplicates()

#     数据类型转换
#         df.astype(), pd.to_numeric(), pd.to_datetime()

#     字符串操作
#         向量化处理：df.str.upper(), df.str.contains(), 正则表达式




# ------------------------缺失值处理----------------------------

import pandas as pd
import numpy as np

# 创建示例数据
data = {'A': [1, np.nan, 3, 4, np.nan],
        'B': ['a', 'b', np.nan, 'd', 'e'],
        'C': [0.1, 0.2, 0.3, np.nan, 0.5],
        'D': ['2023-01', None, '2023-03', '2023-04', '']}
df = pd.DataFrame(data)
print("原始数据：\n", df)


# 检测缺失值
print("缺失值检测：\n", df.isna())  # 等价于 df.isnull()
# 统计每列缺失值数量
print("\n列缺失统计：\n", df.isna().sum())

# 删除缺失值
df_drop = df.dropna(axis=0, how='any', subset=['A', 'C'])
print("\n删除缺失值后：\n", df_drop)


# 填充缺失值
df_fill = df.fillna({'A': df['A'].mean(),  # 数值列用均值填充
                     'B': 'unknown',       # 字符列用固定值
                     'C': df['C'].ffill(), # 向前填充
                     'D': 'missing'})      # 自定义填充
print("\n填充后：\n", df_fill)

# 插值法（时间序列常用）
df['C_interp'] = df['C'].interpolate(method='linear')  # 线性插值
print("\n插值处理：\n", df[['C', 'C_interp']])








# 数据选择与索引
# 基本索引
#     列选择：df['col'], df[['col1', 'col2']]
#     行选择：df[0:5]
#     标签索引：df.loc[row_label, col_label]
#     位置索引：df.iloc[row_idx, col_idx]
#     布尔索引：df[df['col'] > 10]

#     多级索引（Hierarchical Index）
#         创建：pd.MultiIndex
#         操作：df.stack(), df.unstack()